home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / amyboard / xboard-3.3.pl0 / parser.l < prev    next >
Text File  |  1995-08-12  |  23KB  |  905 lines

  1. %a 9000
  2. %o 10000
  3. %e 2000
  4. %k 2500
  5. %p 7000
  6. %n 1000
  7. %{
  8. /*
  9.  * parser.l -- lex parser of algebraic chess moves for XBoard
  10.  * $Id: parser.l,v 1.27 1995/07/28 05:23:42 mann Exp $
  11.  *
  12.  * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
  13.  * Enhancements Copyright 1992-95 Free Software Foundation, Inc.
  14.  *
  15.  * The following terms apply to Digital Equipment Corporation's copyright
  16.  * interest in XBoard:
  17.  * ------------------------------------------------------------------------
  18.  * All Rights Reserved
  19.  *
  20.  * Permission to use, copy, modify, and distribute this software and its
  21.  * documentation for any purpose and without fee is hereby granted,
  22.  * provided that the above copyright notice appear in all copies and that
  23.  * both that copyright notice and this permission notice appear in
  24.  * supporting documentation, and that the name of Digital not be
  25.  * used in advertising or publicity pertaining to distribution of the
  26.  * software without specific, written prior permission.
  27.  *
  28.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  29.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  30.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  31.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  32.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  33.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  34.  * SOFTWARE.
  35.  * ------------------------------------------------------------------------
  36.  *
  37.  * The following terms apply to the enhanced version of XBoard distributed
  38.  * by the Free Software Foundation:
  39.  * ------------------------------------------------------------------------
  40.  * This program is free software; you can redistribute it and/or modify
  41.  * it under the terms of the GNU General Public License as published by
  42.  * the Free Software Foundation; either version 2 of the License, or
  43.  * (at your option) any later version.
  44.  *
  45.  * This program is distributed in the hope that it will be useful,
  46.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  47.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  48.  * GNU General Public License for more details.
  49.  *
  50.  * You should have received a copy of the GNU General Public License
  51.  * along with this program; if not, write to the Free Software
  52.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  53.  * ------------------------------------------------------------------------
  54.  */
  55.  
  56. /* This parser handles all forms of promotion.
  57.  * The parser resolves ambiguous moves by searching and check-testing.
  58.  * It also parses comments of the form [anything] or (anything).
  59.  */
  60.  
  61. #include <config.h>
  62.  
  63. #define NO_CONSTRAINT    -1
  64. #undef YYLMAX
  65. #define YYLMAX            4096
  66. #define UNPUT_BUF_SIZE        YYLMAX
  67.  
  68. #ifdef FLEX_SCANNER
  69. /* typeof(yytext) == "char *" */
  70. /* yy_text is set in YY_DECL below */
  71. char *yy_text;
  72. #else /*!FLEX_SCANNER*/
  73. /* typeof(yytext) == "char []" */
  74. char *yy_text = (char *) yytext;
  75. #endif
  76.  
  77. #ifdef FLEX_SCANNER
  78. /* This is flex */
  79. #undef YY_INPUT
  80. #define YY_INPUT(buf, result, max_size) my_yy_input(buf, &result, max_size)
  81. #undef YY_DECL
  82. #define YY_DECL                     \
  83.     int _yylex YY_PROTO((void));    \
  84.     int yylex YY_PROTO((void))      \
  85.     {                               \
  86.     int result = _yylex();      \
  87.     yy_text = (char *) yytext;  \
  88.     return(result);             \
  89.     }                               \
  90.     int _yylex YY_PROTO((void))
  91. #else
  92. /* This is lex */
  93. #undef input
  94. #undef output
  95. #undef unput
  96. #endif
  97.  
  98. /* The includes must be here, below the #undef input */
  99.  
  100. #include <ctype.h>
  101.  
  102. # if HAVE_STRING_H
  103. #  include <string.h>
  104. # else /* not HAVE_STRING_H */
  105. #  include <strings.h>
  106. # endif /* not HAVE_STRING_H */
  107.  
  108. #if HAVE_UNISTD_H
  109. # include <unistd.h>
  110. #endif
  111.  
  112. #if defined(_amigados)
  113. # include <errno.h>
  114. # if HAVE_FCNTL_H
  115. #  include <fcntl.h>    /*  isatty() prototype  */
  116. # endif /*  HAVE_FCNTL_H        */
  117. #endif  /*  defined(_amigados)  */
  118.  
  119. #include "common.h"
  120. #include "backend.h"
  121. #include "frontend.h"
  122. #include "parser.h"
  123. #include "moves.h"
  124.  
  125. #define FakeFlags(index) \
  126.     (((((index) % 2) == 0) ? F_WHITE_ON_MOVE : 0) | F_ALL_CASTLE_OK)
  127.  
  128. extern Board    boards[MAX_MOVES];
  129. int        yyboardindex;
  130. int             yyskipmoves = FALSE;
  131. char        currentMoveString[YYLMAX];
  132. #ifndef FLEX_SCANNER
  133. char        unputBuffer[UNPUT_BUF_SIZE];
  134. int        unputCount = 0;
  135. #endif
  136.  
  137. #ifdef FLEX_SCANNER
  138. void my_yy_input P((char *buf, int *result, int max_size));
  139. #else /*!FLEX_SCANNER*/
  140. static int input P((void));
  141. static void output P((int ch));
  142. static void unput P((int ch));
  143. int yylook P((void));
  144. int yyback P((int *, int));
  145. #endif
  146. #undef yywrap
  147. int yywrap P((void));
  148. extern void CopyBoard P((Board to, Board from));
  149.  
  150. %}
  151. %%
  152.  
  153. [RrBbNnQqKkPp][/]?[a-h][1-8][xX:-]?[a-h][1-8](=?\(?[RrBbNnQq]\)?)? {
  154.     /*
  155.      * Fully-qualified algebraic move, possibly with promotion
  156.      */
  157.     int skip1 = 0, skip2 = 0;
  158.     ChessSquare piece;
  159.     ChessMove result;
  160.     
  161.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  162.  
  163.     /* remove the / */
  164.     if (yytext[1] == '/') skip1 = 1;
  165.     
  166.     /* remove the [xX:-] */
  167.     if ((yytext[3+skip1] == 'x') || (yytext[3+skip1] == 'X') ||
  168.     (yytext[3+skip1] == '-') || (yytext[3+skip1] == ':')) skip2 = 1;
  169.     
  170.     currentMoveString[0] = yytext[1+skip1];
  171.     currentMoveString[1] = yytext[2+skip1];
  172.     currentMoveString[2] = yytext[3+skip1+skip2];
  173.     currentMoveString[3] = yytext[4+skip1+skip2];
  174.     currentMoveString[4] = NULLCHAR;
  175.     
  176.     if (yyleng-skip1-skip2 > 5) {
  177.     if (yytext[yyleng-1] == ')') {
  178.         currentMoveString[4] = ToLower(yytext[yyleng-2]);
  179.     } else {
  180.         currentMoveString[4] = ToLower(yytext[yyleng-1]);
  181.     }
  182.     currentMoveString[5] = NULLCHAR;
  183.     }
  184.  
  185.     piece = boards[yyboardindex]
  186.       [currentMoveString[1] - '1'][currentMoveString[0] - 'a'];
  187.     if (ToLower(yytext[0]) != ToLower(PieceToChar(piece)))
  188.       return (int) BadMove;
  189.  
  190.     result = LegalityTest(boards[yyboardindex],
  191.               FakeFlags(yyboardindex), EP_UNKNOWN,
  192.               currentMoveString[1] - '1',
  193.               currentMoveString[0] - 'a',
  194.               currentMoveString[3] - '1',
  195.               currentMoveString[2] - 'a',
  196.               currentMoveString[4]);
  197.  
  198.     if (currentMoveString[4] == NULLCHAR &&
  199.     (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
  200.     currentMoveString[4] = 'q';
  201.     currentMoveString[5] = NULLCHAR;
  202.     }
  203.  
  204.     return (int) result;
  205. }
  206.  
  207. [a-h][1-8][xX:-]?[a-h][1-8](=?\(?[RrBbNnQq]\)?)?    {
  208.     /*
  209.      * Simple algebraic move, possibly with promotion
  210.      */
  211.     int skip = 0;
  212.     ChessMove result;
  213.  
  214.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  215.  
  216.     /* remove the [xX:-] */
  217.     if ((yytext[2] == 'x') || (yytext[2] == 'X') ||
  218.     (yytext[2] == '-') || (yytext[2] == ':')) skip = 1;
  219.  
  220.     currentMoveString[0] = yytext[0];
  221.     currentMoveString[1] = yytext[1];
  222.     currentMoveString[2] = yytext[2+skip];
  223.     currentMoveString[3] = yytext[3+skip];
  224.     currentMoveString[4] = NULLCHAR;
  225.  
  226.     if (yyleng-skip > 4) {
  227.     if (yytext[yyleng-1] == ')') {
  228.         currentMoveString[4] = ToLower(yytext[yyleng-2]);
  229.     } else {
  230.         currentMoveString[4] = ToLower(yytext[yyleng-1]);
  231.     }
  232.     currentMoveString[5] = NULLCHAR;
  233.     }
  234.  
  235.     result = LegalityTest(boards[yyboardindex],
  236.               FakeFlags(yyboardindex), EP_UNKNOWN,
  237.               currentMoveString[1] - '1',
  238.               currentMoveString[0] - 'a',
  239.               currentMoveString[3] - '1',
  240.               currentMoveString[2] - 'a',
  241.               currentMoveString[4]);
  242.  
  243.     if (currentMoveString[4] == NULLCHAR &&
  244.     (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
  245.     currentMoveString[4] = 'q';
  246.     currentMoveString[5] = NULLCHAR;
  247.     }
  248.  
  249.     return (int) result;
  250. }
  251.  
  252. [a-h][1-8](=?\(?[RrBbNnQq]\)?)?    {
  253.     /*
  254.      * Pawn move, possibly with promotion
  255.      */
  256.     DisambiguateClosure cl;
  257.     int skip = 0;
  258.  
  259.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  260.  
  261.     /* remove the =() */
  262.     if (yytext[2] == '=') skip++;
  263.     if (yytext[2+skip] == '(') skip++;
  264.  
  265.     cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn;
  266.     cl.rfIn = -1;
  267.     cl.ffIn = yytext[0] - 'a';
  268.     cl.rtIn = yytext[1] - '1';
  269.     cl.ftIn = yytext[0] - 'a';
  270.     cl.promoCharIn = yytext[2+skip];
  271.     Disambiguate(boards[yyboardindex],
  272.          FakeFlags(yyboardindex), EP_UNKNOWN, &cl);
  273.  
  274.     currentMoveString[0] = cl.ff + 'a';
  275.     currentMoveString[1] = cl.rf + '1';
  276.     currentMoveString[2] = cl.ft + 'a';
  277.     currentMoveString[3] = cl.rt + '1';
  278.     currentMoveString[4] = cl.promoChar;
  279.     currentMoveString[5] = NULLCHAR;
  280.  
  281.     return (int) cl.kind;
  282. }
  283.  
  284.  
  285. (ab|bc|cd|de|ef|fg|gh|hg|gf|fe|ed|dc|cb|ba|([a-h][xX:-][a-h]))(=?\(?[RrBbNnQq]\)?)? {
  286.     /*
  287.      * Pawn capture, possibly with promotion, possibly ambiguous
  288.      */
  289.     DisambiguateClosure cl;
  290.     int skip1 = 0, skip2 = 0;
  291.  
  292.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  293.  
  294.     /* remove the [xX:-] and =() */
  295.     if ((yytext[1] == 'x') || (yytext[1] == 'X')
  296.     || (yytext[1] == ':') || (yytext[1] == '-')) skip1 = 1;
  297.     if (yytext[2+skip1] == '=') skip2++;
  298.     if (yytext[2+skip1+skip2] == '(') skip2++;
  299.  
  300.     cl.pieceIn = WhiteOnMove(yyboardindex) ? WhitePawn : BlackPawn;
  301.     cl.rfIn = -1;
  302.     cl.ffIn = yytext[0] - 'a';
  303.     cl.rtIn = -1;
  304.     cl.ftIn = yytext[1+skip1] - 'a';
  305.     cl.promoCharIn = yytext[2+skip1+skip2];
  306.     Disambiguate(boards[yyboardindex],
  307.          FakeFlags(yyboardindex), EP_UNKNOWN, &cl);
  308.  
  309.     currentMoveString[0] = cl.ff + 'a';
  310.     currentMoveString[1] = cl.rf + '1';
  311.     currentMoveString[2] = cl.ft + 'a';
  312.     currentMoveString[3] = cl.rt + '1';
  313.     currentMoveString[4] = cl.promoChar;
  314.     currentMoveString[5] = NULLCHAR;
  315.  
  316.     return (int) cl.kind;
  317. }
  318.  
  319. [a-h][xX:]?[a-h][1-8](=?\(?[RrBbNnQq]\)?)?    {
  320.     /*
  321.      * unambiguously abbreviated Pawn capture, possibly with promotion
  322.      */
  323.     int skip = 0;
  324.     ChessMove result;
  325.  
  326.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  327.  
  328.     /* remove the [xX:-] */
  329.     if ((yytext[1] == 'x') || (yytext[1] == 'X')
  330.     || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1;
  331.  
  332.     currentMoveString[0] = yytext[0];
  333.     currentMoveString[2] = yytext[1+skip];
  334.     currentMoveString[3] = yytext[2+skip];
  335.     if (WhiteOnMove(yyboardindex)) {
  336.     if (yytext[2+skip] == '1') return (int) BadMove;
  337.     currentMoveString[1] = yytext[2+skip] - 1;
  338.     } else {
  339.     if (yytext[2+skip] == '8') return (int) BadMove;
  340.     currentMoveString[1] = yytext[2+skip] + 1;
  341.     }
  342.     if (yyleng-skip > 3) {
  343.     if (yytext[yyleng-1] == ')')
  344.       currentMoveString[4] = ToLower(yytext[yyleng-2]);
  345.     else
  346.       currentMoveString[4] = ToLower(yytext[yyleng-1]);
  347.     currentMoveString[5] = NULLCHAR;
  348.     } else {
  349.     currentMoveString[4] = NULLCHAR;
  350.     }
  351.  
  352.     result = LegalityTest(boards[yyboardindex],
  353.               FakeFlags(yyboardindex), EP_UNKNOWN,
  354.               currentMoveString[1] - '1',
  355.               currentMoveString[0] - 'a',
  356.               currentMoveString[3] - '1',
  357.               currentMoveString[2] - 'a',
  358.               currentMoveString[4]);
  359.  
  360.     if (currentMoveString[4] == NULLCHAR &&
  361.     (result == WhitePromotionQueen || result == BlackPromotionQueen)) {
  362.     currentMoveString[4] = 'q';
  363.     currentMoveString[5] = NULLCHAR;
  364.     }
  365.  
  366.     if (result != BadMove) return (int) result;
  367.  
  368.     /* Special case: improperly written en passant capture */
  369.     if (WhiteOnMove(yyboardindex)) {
  370.     if (currentMoveString[3] == '5') {
  371.         currentMoveString[1] = '5';
  372.         currentMoveString[3] = '6';
  373.     } else {
  374.         return (int) BadMove;
  375.     }
  376.     } else {
  377.     if (currentMoveString[3] == '4') {
  378.         currentMoveString[1] = '4';
  379.         currentMoveString[3] = '3';
  380.     } else {
  381.         return (int) BadMove;
  382.     }
  383.     }
  384.  
  385.     result = LegalityTest(boards[yyboardindex],
  386.               FakeFlags(yyboardindex), EP_UNKNOWN,
  387.               currentMoveString[1] - '1',
  388.               currentMoveString[0] - 'a',
  389.               currentMoveString[3] - '1',
  390.               currentMoveString[2] - 'a',
  391.               currentMoveString[4]);
  392.  
  393.     if (result == WhiteCapturesEnPassant || result == BlackCapturesEnPassant)
  394.       return (int) result;
  395.     else
  396.       return (int) BadMove;
  397. }
  398.  
  399. [RrBbNnQqKk][xX:-]?[a-h][1-8]  {
  400.     /*
  401.      * piece move, possibly ambiguous
  402.      */
  403.     DisambiguateClosure cl;
  404.     int skip = 0;
  405.  
  406.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  407.  
  408.     /* remove the [xX:-] */
  409.     if ((yytext[1] == 'x') || (yytext[1] == 'X')
  410.     || (yytext[1] == ':') || (yytext[1] == '-')) skip = 1;
  411.  
  412.     if (WhiteOnMove(yyboardindex)) {
  413.     cl.pieceIn = CharToPiece(ToUpper(yytext[0]));
  414.     } else {
  415.     cl.pieceIn = CharToPiece(ToLower(yytext[0]));
  416.     }
  417.     cl.rfIn = -1;
  418.     cl.ffIn = -1;
  419.     cl.rtIn = yytext[2+skip] - '1';
  420.     cl.ftIn = yytext[1+skip] - 'a';
  421.     cl.promoCharIn = NULLCHAR;
  422.     Disambiguate(boards[yyboardindex],
  423.          FakeFlags(yyboardindex), EP_UNKNOWN, &cl);
  424.  
  425.     currentMoveString[0] = cl.ff + 'a';
  426.     currentMoveString[1] = cl.rf + '1';
  427.     currentMoveString[2] = cl.ft + 'a';
  428.     currentMoveString[3] = cl.rt + '1';
  429.     currentMoveString[4] = cl.promoChar;
  430.     currentMoveString[5] = NULLCHAR;
  431.  
  432.     return (int) cl.kind;
  433. }
  434.  
  435. [RrBbNnQqKk][a-h1-8][xX:-]?[a-h][1-8]    {
  436.     /*
  437.      * piece move with rank or file disambiguator
  438.      */
  439.     DisambiguateClosure cl;
  440.     int skip = 0;
  441.  
  442.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  443.  
  444.     /* remove the [xX:-] */
  445.     if ((yytext[2] == 'x') || (yytext[2] == 'X')
  446.     || (yytext[2] == ':') || (yytext[2] == '-')) skip = 1;
  447.  
  448.     if (WhiteOnMove(yyboardindex)) {
  449.     cl.pieceIn = CharToPiece(ToUpper(yytext[0]));
  450.     } else {
  451.     cl.pieceIn = CharToPiece(ToLower(yytext[0]));
  452.     }
  453.     if (isalpha(yytext[1])) {
  454.     cl.rfIn = -1;
  455.     cl.ffIn = yytext[1] - 'a';
  456.     } else {
  457.     cl.rfIn = yytext[1] - '1';
  458.     cl.ffIn = -1;
  459.     }
  460.     cl.rtIn = yytext[3+skip] - '1';
  461.     cl.ftIn = yytext[2+skip] - 'a';
  462.     cl.promoCharIn = NULLCHAR;
  463.     Disambiguate(boards[yyboardindex],
  464.          FakeFlags(yyboardindex), EP_UNKNOWN, &cl);
  465.  
  466.     currentMoveString[0] = cl.ff + 'a';
  467.     currentMoveString[1] = cl.rf + '1';
  468.     currentMoveString[2] = cl.ft + 'a';
  469.     currentMoveString[3] = cl.rt + '1';
  470.     currentMoveString[4] = cl.promoChar;
  471.     currentMoveString[5] = NULLCHAR;
  472.  
  473.     return (int) cl.kind;
  474. }
  475.  
  476. 000|0-0-0|ooo|OOO|o-o-o|O-O-O    {
  477.     int rf, ff, rt, ft;
  478.  
  479.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  480.  
  481.     if (WhiteOnMove(yyboardindex)) {
  482.     if (boards[yyboardindex][0][3] == WhiteKing) {
  483.         /* ICS wild castling */
  484.         strcpy(currentMoveString, "d1f1");
  485.         rf = 0;
  486.         ff = 3;
  487.         rt = 0;
  488.         ft = 5;
  489.     } else {
  490.         strcpy(currentMoveString, "e1c1");
  491.         rf = 0;
  492.         ff = 4;
  493.         rt = 0;
  494.         ft = 2;
  495.     }
  496.     } else{ 
  497.     if (boards[yyboardindex][7][3] == BlackKing) {
  498.         /* ICS wild castling */
  499.         strcpy(currentMoveString, "d8f8");
  500.         rf = 7;
  501.         ff = 3;
  502.         rt = 7;
  503.         ft = 5;
  504.     } else {
  505.         strcpy(currentMoveString, "e8c8");
  506.         rf = 7;
  507.         ff = 4;
  508.         rt = 7;
  509.         ft = 2;
  510.     }
  511.     }
  512.     return (int) LegalityTest(boards[yyboardindex],
  513.                   FakeFlags(yyboardindex), EP_UNKNOWN,
  514.                   rf, ff, rt, ft, NULLCHAR);
  515. }
  516.  
  517. 00|0-0|oo|OO|o-o|O-O    {
  518.     int rf, ff, rt, ft;
  519.  
  520.     if (yyskipmoves) return (int) AmbiguousMove; /* not disambiguated */
  521.  
  522.     if (WhiteOnMove(yyboardindex)) {
  523.     if (boards[yyboardindex][0][3] == WhiteKing) {
  524.         /* ICS wild castling */
  525.         strcpy(currentMoveString, "d1b1");
  526.         rf = 0;
  527.         ff = 3;
  528.         rt = 0;
  529.         ft = 1;
  530.     } else {
  531.         strcpy(currentMoveString, "e1g1");
  532.         rf = 0;
  533.         ff = 4;
  534.         rt = 0;
  535.         ft = 6;
  536.     }
  537.     } else {
  538.     if (boards[yyboardindex][7][3] == BlackKing) {
  539.         /* ICS wild castling */
  540.         strcpy(currentMoveString, "d8b8");
  541.         rf = 7;
  542.         ff = 3;
  543.         rt = 7;
  544.         ft = 1;
  545.     } else {
  546.         strcpy(currentMoveString, "e8g8");
  547.         rf = 7;
  548.         ff = 4;
  549.         rt = 7;
  550.         ft = 6;
  551.     }
  552.     }
  553.     return (int) LegalityTest(boards[yyboardindex],
  554.                   FakeFlags(yyboardindex), EP_UNKNOWN,
  555.                   rf, ff, rt, ft, NULLCHAR);
  556. }
  557.  
  558. [Rr](esign|ESIGN)([Ss]|[Ee][Dd])?  {
  559.     if (WhiteOnMove(yyboardindex))
  560.       return (int) BlackWins;
  561.     else
  562.       return (int) WhiteWins;
  563. }
  564.  
  565. [Ww](hite|HITE)?" "(([Rr](esign|ESIGN))|([Ff](orfeit|ORFEIT)))([Ss]|[Ee][Dd])?  {
  566.     return (int) BlackWins;
  567. }
  568.  
  569. [Bb](lack|LACK)?" "(([Rr](esign|ESIGN))|([Ff](orfeit|ORFEIT)))([Ss]|[Ee][Dd])?  {
  570.     return (int) WhiteWins;
  571. }
  572.  
  573. [Ww](hite|HITE)?" "[Aa](sserts|SSERTS)" "([aA]" ")?[Ww](in|IN)  {
  574.     return (int) WhiteWins;
  575. }
  576.  
  577. [Bb](lack|LACK)?" "[Aa](sserts|SSERTS)" "([aA]" ")?[Ww](in|IN)  {
  578.     return (int) BlackWins;
  579. }
  580.  
  581. ([Ww](hite|HITE)|[Bb](lack|LACK))" "[dD](isconnect|ISCONNECT)([Ss]|[Ee][Dd]) {
  582.     return (int) GameUnfinished;
  583. }
  584.  
  585. [Ss](talemate|TALEMATE)  {
  586.     return (int) GameIsDrawn;
  587. }
  588.  
  589. "+-+"  {
  590.     return (int) GameIsDrawn;
  591. }
  592.  
  593. ([Cc](heck|HECK))?[Mm](ate|ATE)  {
  594.     if (WhiteOnMove(yyboardindex))
  595.       return (int) BlackWins;
  596.     else
  597.       return (int) WhiteWins;
  598. }
  599.  
  600. "++"  {
  601.     if (WhiteOnMove(yyboardindex))
  602.       return (int) BlackWins;
  603.     else
  604.       return (int) WhiteWins;
  605. }
  606.  
  607. ([Bb](lack|LACK)?|[Ww](hite|HITE)?)" "[Oo](ffers|FFERS)" "[Dd](raw|RAW)[Nn]?  {
  608.     return (int) GameIsDrawn;
  609. }
  610.  
  611. [Dd](raw|RAW)[Nn]?(" "[Bb][Yy])?(" "[Rr](epetition|EPETITION)|" "[Aa](gree|GREE)([Dd]|(ment|MENT))?) {
  612.     return (int) GameIsDrawn;
  613. }
  614.  
  615. [Dd](raw|RAW)[Nn]?(" (".*")")?  {
  616.     return (int) GameIsDrawn;
  617. }
  618.  
  619. [Ww](hite|HITE)?(" "[Ww][IiOo][Nn][Ss]?(" "[Oo][Nn]" "[Tt](ime|IME))?(" (".*")")?|" "[Mm](ates|ATES))? { 
  620.     return (int) WhiteWins;
  621. }
  622.  
  623. [Bb](lack|LACK)?(" "[Ww][IiOo][Nn][Ss]?(" "[Oo][Nn]" "[Tt](ime|IME))?(" (".*")")?|" "[Mm](ates|ATES))? { 
  624.     return (int) BlackWins;
  625. }
  626.  
  627. [Ww](hite|HITE)?" "[Ll][Oo][Ss]([Tt]|[Es][Ss])(" "[Oo][Nn]" "[Tt](ime|IME))? { 
  628.     return (int) BlackWins;
  629. }
  630.  
  631. [Bb](lack|LACK)?" "[Ll][Oo][Ss]([Tt]|[Es][Ss])(" "[Oo][Nn]" "[Tt](ime|IME))? { 
  632.     return (int) WhiteWins;
  633. }
  634.  
  635. ("{"[^\}\n]*"} ")?(1-0|"1 - 0"|"1/0"|"1 / 0"|"1:0"|"1 : 0")(" (".*")"|" {".*"}")? { 
  636.     return (int) WhiteWins;
  637. }
  638.  
  639. ("{"[^\}\n]*"} ")?(0-1|"0 - 1"|"0/1"|"0 / 1"|"0:1"|"0 : 1")(" (".*")"|" {".*"}")? { 
  640.     return (int) BlackWins;
  641. }
  642.  
  643. ("{"[^\}\n]*"} ")?("1/2"|"1 / 2")(" "?[-:]" "?("1/2"|"1 / 2"))?(" (".*")"|" {".*"}")? {
  644.     return (int) GameIsDrawn;
  645. }
  646.  
  647. ("{"[^\}\n]*"} ")?"*"(" (".*")"|" {".*"}")? {
  648.     return (int) GameUnfinished;
  649. }
  650.  
  651. [1-9][0-9]*/[. \t\n]*[a-hNnPpRrBQqKk]    {
  652.     /* move numbers */
  653.     if ((yyleng == 1) && (yytext[0] == '1'))
  654.       return (int) MoveNumberOne;
  655. }
  656.  
  657. \([0-9]+:[0-9][0-9]\)|\{[0-9]+:[0-9][0-9]\} {
  658.     /* elapsed time indication, e.g. (0:12) */ 
  659.     return (int) ElapsedTime;
  660. }
  661.  
  662. "[--"[^\]]*"--]" {
  663.     /* position diagram enclosed in [-- --] */
  664.     return (int) PositionDiagram;
  665. }
  666.  
  667. ^"{--------------"\n[^\}]*\n"--------------}"$ {
  668.     /* position diagram enclosed in {-- --} */
  669.     return (int) PositionDiagram;
  670. }
  671.  
  672. \[[ \t\n]*[A-Za-z0-9][A-Za-z0-9_+#=-]*[ \t\n]*\"[^"]*\"[ \t\n]*\] {
  673.     return (int) PGNTag;
  674. }    
  675.  
  676. [Gg](nu|NU)" "?[Cc](hess|HESS).*[Gg](ame|AME) {
  677.     return (int) GNUChessGame;
  678. }
  679.  
  680. ^[#;%]" "[^ ]*(" game file"|" position file").*$ {
  681.     return (int) XBoardGame;
  682. }
  683.  
  684. \{[^\}]*\}    {                    /* anything in {} */
  685.     return (int) Comment; 
  686. }
  687.  
  688. ;.*$ {                                          /* ; to end of line */
  689.     return (int) Comment;
  690. }
  691.  
  692. \[[^\]]*\]    {                    /* anything in [] */
  693.     return (int) Comment; 
  694. }
  695.  
  696. \([^()]*(\([^()]*\))+[^()]*\)  {           /* nested () */
  697.     return (int) Comment; 
  698. }
  699.  
  700. \([^)][^)]+\)   {                 /* >=2 chars in () */
  701.     return (int) Comment; 
  702. }       
  703.  
  704. ^[-a-zA-Z0-9]+:.*(\n[ \t]+.*)*  {
  705.         /* Skip mail headers */
  706. }
  707.  
  708. [a-zA-Z0-9'-]+            {
  709.         /* Skip random words */
  710. }
  711.  
  712. .|"\n"                {
  713.         /* Skip everything else */
  714. }
  715.  
  716. %%
  717.  
  718.  
  719. static char *StringToLex;
  720.  
  721. #ifndef FLEX_SCANNER
  722. static FILE *lexFP;
  723.  
  724. static int input()
  725. {
  726.     int ret;
  727.     
  728.     if (StringToLex != NULL) {
  729.     ret = *StringToLex;
  730.     if (ret == NULLCHAR)
  731.       ret = EOF;
  732.     else
  733.       StringToLex++;
  734.     } else if (unputCount > 0) {
  735.     ret = unputBuffer[--unputCount];
  736.     } else {
  737.     ret = fgetc(lexFP);
  738.     }    
  739.  
  740.     if (ret == EOF) 
  741.       return 0;
  742.     else
  743.       return ret;
  744. }
  745.  
  746. /*
  747.  * Return offset of next pattern within current file
  748.  */
  749. int yyoffset()
  750. {
  751.     int offset = ftell(lexFP) - unputCount;
  752.  
  753.     if (offset < 0) {
  754.     offset = 0;
  755.     }
  756.     return(offset);
  757. }
  758.  
  759. static void output(ch)
  760.      int ch;
  761. {
  762.     fprintf(stderr, "PARSER BUG: unmatched character '%c' (0%o)\n",
  763.         ch, ch);
  764. }
  765.  
  766. static void unput(ch)
  767.      int ch;
  768. {
  769.     if (ch == 0) return;
  770.     if (StringToLex != NULL) {
  771.     StringToLex--;
  772.     } else {
  773.     if (unputCount >= UNPUT_BUF_SIZE)
  774.       fprintf(stderr, "PARSER BUG: unput buffer overflow '%c' (0%o)\n",
  775.           ch, ch);
  776.     unputBuffer[unputCount++] = ch;
  777.     }
  778. }
  779.  
  780. /* Get ready to lex from a new file.  Kludge below sticks
  781.    an artificial newline at the front of the file, which the
  782.    above grammar ignores, but which makes ^ at start of pattern
  783.    match at the real start of the file.
  784. */
  785. void yynewfile(f)
  786.      FILE *f;
  787. {
  788.     lexFP = f;
  789.     StringToLex = NULL;
  790.     unputCount = 0;
  791.     unput('\n'); /* kludge */
  792. }
  793.  
  794. /* Get ready to lex from a string.  ^ at start of pattern WON'T
  795.    match at the start of the string!
  796. */
  797. void yynewstr(s)
  798.      char *s;
  799. {
  800.     lexFP = NULL;
  801.     StringToLex = s;
  802.     unputCount = 0;
  803. }
  804. #endif /*!FLEX_SCANNER*/
  805.  
  806. #ifdef FLEX_SCANNER
  807. void my_yy_input(buf, result, max_size)
  808.      char *buf;
  809.      int *result;
  810.      int max_size;
  811. {
  812.     int count;
  813.  
  814.     if (StringToLex != NULL) {
  815.     count = 0;
  816.     while (*StringToLex != NULLCHAR) {
  817.         *buf++ = *StringToLex++;
  818.         count++;
  819.     }
  820.     *result = count;
  821.     return;
  822.     } else {
  823.     count = fread(buf, 1, max_size, yyin);
  824.     if (count == 0) {
  825.         *result = YY_NULL;
  826.     } else {
  827.         *result = count;
  828.     }
  829.     return;
  830.     }    
  831. }
  832.  
  833. static YY_BUFFER_STATE my_file_buffer = NULL;
  834.  
  835. /*
  836.     Return offset of next pattern in the current file.
  837. */
  838. int yyoffset()
  839. {
  840.     int pos = yy_c_buf_p - yy_current_buffer->yy_ch_buf;
  841.  
  842.     return(ftell(yy_current_buffer->yy_input_file) -
  843.          yy_n_chars + pos);
  844. }
  845.  
  846.  
  847. void yynewstr(s)
  848.      char *s;
  849. {
  850.     if (my_file_buffer != NULL)
  851.       yy_delete_buffer(my_file_buffer);
  852.     StringToLex = s;
  853.     my_file_buffer = yy_create_buffer(stdin, YY_BUF_SIZE);
  854.     yy_switch_to_buffer(my_file_buffer);
  855. }
  856.  
  857. void yynewfile(f)
  858.      FILE *f;
  859. {
  860.     if (my_file_buffer != NULL)
  861.       yy_delete_buffer(my_file_buffer);
  862.     StringToLex = NULL;
  863.     my_file_buffer = yy_create_buffer(f, YY_BUF_SIZE);
  864.     yy_switch_to_buffer(my_file_buffer);
  865. }
  866. #endif /*FLEX_SCANNER*/
  867.  
  868. int yywrap()
  869. {
  870.     return TRUE;
  871. }
  872.  
  873. /* Parse a move from the given string s */
  874. /* ^ at start of pattern WON'T work here unless using flex */
  875. ChessMove yylexstr(boardIndex, s)
  876.      int boardIndex;
  877.      char *s;
  878. {
  879.     ChessMove ret;
  880.     char *oldStringToLex;
  881. #ifdef FLEX_SCANNER
  882.     YY_BUFFER_STATE buffer, oldBuffer;
  883. #endif
  884.     
  885.     yyboardindex = boardIndex;
  886.     oldStringToLex = StringToLex;
  887.     StringToLex = s;
  888. #ifdef FLEX_SCANNER
  889.     buffer = yy_create_buffer(stdin, YY_BUF_SIZE);
  890.     oldBuffer = YY_CURRENT_BUFFER;
  891.     yy_switch_to_buffer(buffer);
  892. #endif /*FLEX_SCANNER*/
  893.  
  894.     ret = (ChessMove) yylex();
  895.  
  896. #ifdef FLEX_SCANNER
  897.     if (oldBuffer != NULL) 
  898.       yy_switch_to_buffer(oldBuffer);
  899.     yy_delete_buffer(buffer);
  900. #endif /*FLEX_SCANNER*/
  901.     StringToLex = oldStringToLex;
  902.  
  903.     return ret;
  904. }
  905.